<template>
  <el-container class="driverContent" @click.native="closePopover">
    <el-aside width="360px" class="leftContent">
      <el-input v-model="filterText" class="filterInput" placeholder="请输入关键字进行过滤">
        <i slot="suffix" class="el-input__icon el-icon-search"></i>
      </el-input>
      <div class="treeContent">
        <el-tree
          ref="tree"
          class="filter-tree"
          :data="treeData"
          highlight-current
          node-key="directoryId"
          :default-expanded-keys="expandedKeys"
          :props="{
            children: 'children',
            label: 'directoryName'
          }"
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          @node-click="(data) => handleNodeClick(data, true)"
          @node-expand="(data) => handleNodeExpand(data, true)"
          @node-collapse="(data) => handleNodeExpand(data, false)"
        >
          <span
            slot-scope="{ node, data }"
            class="treeRow"
            @mouseenter="handleMouseenter(data, true)"
            @mouseleave="handleMouseenter(data, false)"
          >
            <span class="leftText">
              <svg-icon v-if="data.isFile" icon-class="file"></svg-icon>
              <template v-else>
                <svg-icon v-if="data.parentDirectoryId === 0" icon-class="rootFolder"></svg-icon>
                <svg-icon v-else icon-class="folder"></svg-icon>
              </template>
              <span
                style="padding-left: 5px"
                :class="clockTemplateFileId.includes(data.directoryId) ? 'clockTemplate' : ''"
              >
                {{ node.label }}
              </span>
            </span>

            <el-popover
              id="popoverDiv"
              v-model="data.popoverShow"
              popper-class="myPopper"
              placement="right"
              width="172"
              trigger="manual"
            >
              <div class="popoverBtn">
                <div v-permission="['driverLibraryManagement:driverLibrary:projectFileEdit']">
                  <el-link :underline="false" @click="handleClick('edit', data)">编辑</el-link>
                </div>
                <div
                  v-if="data.parentDirectoryId !== 0"
                  v-permission="['driverLibraryManagement:driverLibrary:projectFileDel']"
                >
                  <el-link :underline="false" @click="handleClick('del', data)">删除</el-link>
                </div>
                <div v-permission="['driverLibraryManagement:driverLibrary:projectFileDownload']">
                  <el-link :underline="false" @click="handleClick('download', data)">下载</el-link>
                </div>
                <template v-if="!data.isFile">
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileUploadFile']">
                    <el-link :underline="false" @click="handleClick('uploadFile', data)">上传文件</el-link>
                  </div>
                  <!-- <div v-permission="['driverLibraryManagement:driverLibrary:projectFileUploadFolder']">
                    <el-link :underline="false" @click="handleClick('uploadFolder', data)">上传文件夹</el-link>
                  </div> -->
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileUploadFolder']">
                    <el-link :underline="false" @click="handleClick('uploadFolder1', data)">上传文件夹</el-link>
                  </div>
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileAddChildFolder']">
                    <el-link :underline="false" @click="handleClick('addChildFolder', data)">添加子文件夹</el-link>
                  </div>
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileSetHHeaderDirectory']">
                    <el-link
                      :underline="false"
                      :disabled="data.directoryId === currentProjectData.hHeader?.[0]?.directoryId"
                      @click="handleClick('setH', data)"
                    >
                      设为.h头文件目录
                    </el-link>
                  </div>
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileSetCSourceDirectory']">
                    <el-link
                      :underline="false"
                      :disabled="data.directoryId === currentProjectData.cSource?.[0]?.directoryId"
                      @click="handleClick('setC', data)"
                    >
                      设为.c源文件目录
                    </el-link>
                  </div>
                  <div v-permission="['driverLibraryManagement:driverLibrary:projectFileSetOtherDriverFile']">
                    <el-link
                      :underline="false"
                      :disabled="data.directoryId === currentProjectData.otherDriver?.[0]?.directoryId"
                      @click="handleClick('setOtherDriverFile', data)"
                    >
                      设为其他驱动文件目录
                    </el-link>
                  </div>
                  <div
                    v-permission="[
                      'driverLibraryManagement:driverLibrary:projectFileSetDocumentationSourceDirectory'
                    ]"
                  >
                    <el-link
                      :underline="false"
                      :disabled="data.directoryId === currentProjectData.driverDocumentation?.[0]?.directoryId"
                      @click="handleClick('setDocumentation', data)"
                    >
                      设为说明文档目录
                    </el-link>
                  </div>
                </template>
                <div
                  v-if="data.isFile"
                  v-permission="['driverLibraryManagement:driverLibrary:projectFileSetTemplateFile']"
                >
                  <el-link
                    :underline="false"
                    :disabled="clockTemplateFileId.includes(data.directoryId)"
                    @click.native="handleClick('setTemplate', data)"
                  >
                    设为时钟模板文件
                  </el-link>
                </div>
              </div>
              <i
                v-show="data.show"
                slot="reference"
                class="el-icon-more"
                @click.stop="handleClick('more', data)"
              ></i>
            </el-popover>
          </span>
        </el-tree>
        <input id="uploadFile" style="display: none" type="file" @change="uploadFile" />
        <input id="uploadFolder" style="display: none" type="file" webkitdirectory @change="uploadFolder" />
        <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="378px" :close-on-click-modal="false">
          <el-form
            ref="formData"
            :model="formData"
            :rules="rules"
            :label-width="formData.isFile ? '93px' : '107px'"
            label-suffix="："
          >
            <el-form-item :label="formData.isFile ? '文件名称' : '文件夹名称'" prop="directoryName">
              <el-input
                v-model="formData.directoryName"
                class="show-word-limit"
                :maxlength="formData.isFile ? 48 : 50"
                show-word-limit
              >
                <template v-if="formData.isFile" slot="append">{{ formData.appendName }}</template>
              </el-input>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false">取 消</el-button>
            <el-button type="primary" @click="submitForm">确 定</el-button>
          </span>
        </el-dialog>
        <uploadFolderDialog ref="uploadFolderDialog" @uploadFolder="uploadFolder1" />
      </div>
    </el-aside>
    <el-main class="rightContent">
      <div class="driverSetting">
        <div class="templateFileContent">
          时钟模板文件：
          <el-tag
            v-for="(tag, index) in currentProjectData.clockTemplate"
            :key="tag.directoryId"
            :disable-transitions="false"
            class="myTag"
            :closable="checkPermission('driverLibraryManagement:driverLibrary:projectFileCancelTemplateFileSet')"
            @close="handleClose('clockTemplate', index)"
          >
            {{ tag.directoryName }}
          </el-tag>
        </div>
        <div>
          <span class="left">
            .h头文件目录：
            <el-tag
              v-if="hHeaderFullPath && loading"
              :disable-transitions="false"
              :closable="
                checkPermission('driverLibraryManagement:driverLibrary:projectFileCancelHHeaderDirectorySet')
              "
              class="myTag"
              @close="handleClose('hHeader', 0)"
            >
              {{ hHeaderFullPath }}
            </el-tag>
          </span>
          <span class="right">
            &nbsp;.c源文件目录：
            <el-tag
              v-if="cSourceFullPath && loading"
              :disable-transitions="false"
              :closable="
                checkPermission('driverLibraryManagement:driverLibrary:projectFileCancelCSourceDirectorySet')
              "
              class="myTag"
              @close="handleClose('cSource', 0)"
            >
              {{ cSourceFullPath }}
            </el-tag>
          </span>
        </div>
        <div>
          <div class="left">
            其他驱动文件目录：
            <el-tag
              v-if="otherDriverFullPath && loading"
              :disable-transitions="false"
              :closable="
                checkPermission('driverLibraryManagement:driverLibrary:projectFileCancelOtherDriverFileSet')
              "
              class="myTag"
              @close="handleClose('otherDriver', 0)"
            >
              <span class="ellipsis">{{ otherDriverFullPath }}</span>
            </el-tag>
          </div>
          <div class="right">
            说明文档目录：
            <el-tag
              v-if="documentationFullPath && loading"
              :disable-transitions="false"
              :closable="
                checkPermission('driverLibraryManagement:driverLibrary:projectFileSetDocumentationSourceDirectory')
              "
              class="myTag"
              @close="handleClose('driverDocumentation', 0)"
            >
              {{ documentationFullPath }}
            </el-tag>
          </div>
        </div>
      </div>
      <el-breadcrumb separator="/" class="path">
        <el-breadcrumb-item v-for="item in breadcrumbPath" :key="item.directoryId">
          <el-link :underline="false" @click="handleClick('open', item)">{{ item.directoryName }}</el-link>
        </el-breadcrumb-item>
      </el-breadcrumb>
      <div v-if="!currentData.isFile" class="folderContent">
        <div v-for="item in currentData.children" :key="item.directoryId" class="item">
          <el-link :underline="false" @click="handleClick('open', item)">
            <svg-icon v-if="item.isFile" icon-class="file"></svg-icon>
            <svg-icon v-else icon-class="folder"></svg-icon>
            <span>{{ item.directoryName }}</span>
          </el-link>
        </div>
      </div>
      <div v-else class="codeContent">
        <filePreview :key="codeContentTimer" :content="codeContent" :file-type="currentFileType" />
      </div>
    </el-main>
  </el-container>
</template>

<script>
import {
  loadDriverLibraryDirectoryTree,
  addDriverLibraryConfig,
  editDirectoryName,
  addFolderDriverLibraryDirectory,
  deleteDriverLibraryDirectory,
  downloadDriverLibraryDirectory,
  loadDriverLibraryConfig,
  deleteDriverLibraryConfig,
  uploadFileDriverLibraryDirectory,
  uploadFolderDriverLibraryDirectory
} from '@/api/project-management.js'
import { uploadFolder } from '@/api/system-management'
import uploadFolderDialog from './uploadFolder.vue'
import { downLoadFile, fileDownload } from '@/utils/download.js'
import defaultSettings from '@/settings'
import { generateUUID, postMessage, receivedMessage } from '@/utils/index'
import NProgress from 'nprogress'
import axios from 'axios'
import filePreview from '@/components/filePreview/index'
import { checkPermission } from '@/directive/permission/checkPermission.js' // 权限判断指令
// var validateDirectoryName = (rule, value, callback) => {
//   if (!/^[a-zA-Z][\w-]*$/.test(value)) {
//     callback(new Error(rule.message))
//   }
//   callback()
// }
export default {
  name: 'MasterChipDriver',
  components: { uploadFolderDialog, filePreview },
  props: {
    currentProjectData: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data() {
    return {
      loading: false,
      filterText: '',
      treeData: [],
      expandedKeys: [],
      currentData: {},
      currentOperationData: {},
      popoverNode: {},
      breadcrumbPath: [],
      codeContent: ``,
      codeContentTimer: null,
      dialogTitle: '',
      dialogType: '',
      dialogVisible: false,
      formData: {},
      rules: {},
      newDirectoryId: null,
      acceptReadFileType: [
        '.pdf',
        '.c',
        '.h',
        '.md',
        '.txt',
        '.json',
        '.html',
        '.vue',
        '.js',
        '.css',
        '.scss',
        '.less',
        '.d',
        '.s',
        // '.axf',
        '.ioc',
        // '.o',
        // '.crf',
        '.bat',
        // '.axf',
        '.hex',
        '.htm',
        '.lnp',
        '.map',
        '.sct',
        '.dep',
        // '.pak',
        // '.dat',
        // '.qm',
        // '.cep',
        // '.log',
        '.conf',
        // '.so'
        '.scvd',
        '.lst',
        '.lics',
        '.uvoptx',
        '.uvprojx',
        '.dbgconf',
        '.iex',
        '.ino',
        '.qsf',
        '.v',
        '.'
      ],
      operationType: '',
      driverLibraryConfig: {
        setH: {
          key: 'hHeader',
          configType: 1,
          desc: '设为.h头文件目录成功'
        },
        setC: {
          key: 'cSource',
          configType: 2,
          desc: '设为.c源文件目录成功'
        },
        setTemplate: {
          key: 'clockTemplate',
          configType: 3,
          desc: '设为时钟模板文件成功'
        },
        setDocumentation: {
          key: 'driverDocumentation',
          configType: 4,
          desc: '设为说明文档目录成功'
        },
        setOtherDriverFile: {
          key: 'otherDriver',
          configType: 5,
          desc: '设为其他驱动文件目录成功'
        }
      },

      loadDriverLibraryDirectoryTreeRequestId: generateUUID(),
      addDriverLibraryConfigRequestId: generateUUID(),
      editDirectoryNameRequestId: generateUUID(),
      addFolderDriverLibraryDirectoryRequestId: generateUUID(),
      deleteDriverLibraryDirectoryRequestId: generateUUID(),
      downloadRequestId: generateUUID(),
      downloadDriverLibraryDirectoryRequestId: generateUUID(),
      loadDriverLibraryConfigRequestId: generateUUID(),
      deleteDriverLibraryConfigRequestId: generateUUID(),
      readFileRequestId: generateUUID(),
      currentUploadId: '',
      uploadFolderRequestId: generateUUID(),
      uploadFileOrFolderDriverLibraryDirectoryRequestId: generateUUID()
    }
  },
  computed: {
    currentFileType() {
      let arr = this.currentData.directoryName.split('.').filter((item) => item !== '')
      return arr.length > 1 ? '.' + arr.pop() : '.'
    },
    clockTemplateFileId() {
      return this.currentProjectData?.clockTemplate?.map((item) => item.directoryId) ?? []
    },
    hHeaderFullPath() {
      if (this.currentProjectData?.hHeader?.length > 0) {
        return this.getFullPath(this.currentProjectData.hHeader[0].directoryId)
      } else {
        return ''
      }
    },
    cSourceFullPath() {
      if (this.currentProjectData?.cSource?.length > 0) {
        return this.getFullPath(this.currentProjectData.cSource[0].directoryId)
      } else {
        return ''
      }
    },
    otherDriverFullPath() {
      if (this.currentProjectData?.otherDriver?.length > 0) {
        return this.getFullPath(this.currentProjectData.otherDriver[0].directoryId)
      } else {
        return ''
      }
    },
    documentationFullPath() {
      if (this.currentProjectData?.driverDocumentation?.length > 0) {
        return this.getFullPath(this.currentProjectData.driverDocumentation[0].directoryId)
      } else {
        return ''
      }
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  mounted() {
    receivedMessage(this.dataHandle)
  },
  methods: {
    dataHandle(result) {
      let self = this
      let e = defaultSettings.isWPF ? result : { data: JSON.parse(result) }
      let res = e.data.response
      switch (e.data.webInfo.requestId) {
        case self.loadDriverLibraryDirectoryTreeRequestId:
          self.setTreeData(res)
          break
        case self.addDriverLibraryConfigRequestId:
          if (res.success) {
            self.refreshDriverLibraryConfig()
            self.$message.success(self.driverLibraryConfig[self.operationType].desc)
            self.closePopover(true)
          } else {
            self.$message.error(res.message)
          }
          break
        case self.editDirectoryNameRequestId:
          if (res.success) {
            self.dialogVisible = false
            self.currentOperationData.directoryName = self.formData.directoryName + self.formData.appendName
            // self.handleNodeClick(self.currentData, false)
          } else {
            self.$message.error(res.message)
          }
          break
        case self.addFolderDriverLibraryDirectoryRequestId:
          self.afterAddFolderDriverLibraryDirectory(res)
          break
        case self.deleteDriverLibraryDirectoryRequestId:
          self.delFolderOrFile(res)
          break
        case self.downloadDriverLibraryDirectoryRequestId:
          new Promise((resolve) => {
            if (res.success) {
              var bytes = new Uint8Array(
                window
                  .atob(res.data)
                  .split('')
                  .map(function (c) {
                    return c.charCodeAt(0)
                  })
              )
              res.data = bytes
              fileDownload(res)
            } else {
              self.$message.error(res.message)
            }
            resolve()
          }).then(() => {
            self.closePopover(true)
            NProgress.done()
          })
          break
        case self.downloadRequestId:
          if (res.success) {
            var bytes = new Uint8Array(
              window
                .atob(res.data)
                .split('')
                .map(function (c) {
                  return c.charCodeAt(0)
                })
            )
            res.data = bytes
            fileDownload(res)
            // const blob = new Blob([JSON.stringify(res, null, 2)], { type: 'text/plain;charset=utf-8' })
            // saveAs(blob, self.currentOperationData.directoryName)
            self.closePopover(true)
          } else {
            self.$message.error(res.message)
          }
          break
        case self.loadDriverLibraryConfigRequestId:
          if (res.success) {
            self.currentProjectData.cSource = res.data.cSource
            self.currentProjectData.hHeader = res.data.hHeader
            self.currentProjectData.otherDriver = res.data.otherDriver
            self.currentProjectData.driverDocumentation = res.data.driverDocumentation
            self.currentProjectData.clockTemplate = res.data.clockTemplate
          } else {
            self.$message.error(res.message)
          }
          break
        case self.deleteDriverLibraryConfigRequestId:
          if (res.success) {
            self.refreshDriverLibraryConfig()
          } else {
            self.$message.error(res.message)
          }
          break
        case self.readFileRequestId:
          if (res.success) {
            if (self.currentFileType === '.pdf') {
              self.codeContent = 'data:application/pdf;base64,' + res.data
            } else {
              let uint8Array = Uint8Array.from(atob(res.data), (c) => c.charCodeAt(0))
              let decoder = new TextDecoder()
              let decodedText = decoder.decode(uint8Array)
              // 判断解码后的文本是否包含乱码字符
              const isDecoded = Array.from(decodedText).every((char) => char.charCodeAt(0) !== 65533)
              if (!isDecoded) {
                decoder = new TextDecoder('GBK')
                decodedText = decoder.decode(uint8Array)
              }
              self.codeContent = `${decodedText}`
            }

            self.codeContentTimer = new Date().getTime()
          } else {
            self.$message.error(res.message)
          }
          break
        case self.uploadFolderRequestId:
          // 批量上传文件
          if (res.success) {
            self.uploadFileOrFolderDriverLibraryDirectoryRequestId = generateUUID()
            let message = {
              RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/' + self.currentUploadId,
              RequestMethod: 'POST',
              Headers: {
                contentType: 'application/json'
              },
              QueryParameter: {},
              RequestBody: {
                parentDirectoryId: self.currentOperationData.directoryId,
                directoryFiles: res.data.map((item) => {
                  return {
                    ...item,
                    fileName: item.name,
                    path: item.url
                  }
                })
              },
              WebInfo: {
                requestId: self.uploadFileOrFolderDriverLibraryDirectoryRequestId
              }
            }
            postMessage(message)
          } else {
            self.$message.error(res.message)
            const fileInput = document.getElementById(self.currentUploadId)
            fileInput.value = ''
            NProgress.done()
          }
          break
        case self.uploadFileOrFolderDriverLibraryDirectoryRequestId:
          // 上传完文件后回调
          if (self.currentUploadId) {
            const fileInput = document.getElementById(self.currentUploadId)
            fileInput.value = ''
            //   NProgress.done()
          }
          self.$refs.uploadFolderDialog.handleClose()
          if (res.success) {
            self.loadTreeData(res.data)
          } else {
            self.$message.error(res.message)
          }
          break
      }
    },
    checkPermission(val) {
      return checkPermission(val)
    },
    init() {
      this.currentData = {}
      this.loadTreeData()
    },
    loadTreeData(directoryId = null) {
      this.newDirectoryId = directoryId
      this.loading = !!this.currentData?.directoryId
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.loadDriverLibraryDirectoryTreeRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/loadTree',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { driverLibraryId: this.currentProjectData.driverLibraryId },
          WebInfo: {
            requestId: this.loadDriverLibraryDirectoryTreeRequestId
          }
        }
        postMessage(message)
      } else {
        loadDriverLibraryDirectoryTree({ driverLibraryId: this.currentProjectData.driverLibraryId }).then(
          (res) => {
            this.setTreeData(res)
          }
        )
      }
    },
    setTreeData(res) {
      this.treeData = [res.data]
      this.loading = true

      // this.expandedKeys = []
      this.$nextTick(() => {
        if (!this.currentData?.directoryId) {
          this.expandedKeys = this.getExpandedKeys(this.treeData, [])
          this.$refs.tree.setCurrentKey(this.treeData?.[0]?.directoryId)
          this.handleNodeClick(this.treeData?.[0], false)
        } else {
          if (this.newDirectoryId) {
            let currentData = this.findNode(this.treeData, 'directoryId', this.newDirectoryId, [])
            this.$refs.tree.setCurrentKey(currentData.directoryId)
            if (!this.expandedKeys.includes(currentData.parentDirectoryId)) {
              this.expandedKeys.push(currentData.parentDirectoryId)
            }
            this.handleNodeClick(currentData, false)
          } else {
            this.$refs.tree.setCurrentKey(this.currentData.directoryId)
            this.currentData = this.findNode(this.treeData, 'directoryId', this.currentData.directoryId, [])
          }
        }
      })
    },
    getExpandedKeys(data, result) {
      data.forEach((item) => {
        result.push(item.directoryId)
        if (item.children) {
          this.getExpandedKeys(item.children, result)
        }
      })
      return result
    },
    handleNodeExpand(data, expanded) {
      if (expanded) {
        // 节点展开时，将其 key 添加到 expandedKeys 数组中
        this.expandedKeys.push(data.directoryId)
      } else {
        // 节点折叠时，从 expandedKeys 数组中移除其 key
        const index = this.expandedKeys.findIndex((item) => item === data.directoryId)
        if (index > -1) {
          this.expandedKeys.splice(index, 1)
          if (data.children) {
            data.children.forEach((item) => {
              this.handleNodeExpand(item, false)
            })
          }
        }
      }
    },
    filterNode(value, data) {
      if (!value) return true
      return data.directoryName.indexOf(value) !== -1
    },
    async handleNodeClick(data, show) {
      if (this.treeData.length > 0) {
        await this.setPopoverShowFalse(this.treeData)
        this.$set(data, 'show', show)
        if (this.currentData.directoryId === data.directoryId) return
      }
      this.currentData = data ?? {}
      let breadcrumbPath = [data]
      if (data.parentDirectoryId !== 0) {
        this.breadcrumbPath = this.getBreadCrumbPath(data, breadcrumbPath)
      } else {
        this.breadcrumbPath = breadcrumbPath
      }
      this.popoverNode = {}
      if (data.isFile) {
        if (data.filePath) {
          let arr = data.directoryName.split('.').filter((item) => item !== '')
          let suffix = arr.length > 1 ? '.' + arr.pop() : '.'
          if (this.acceptReadFileType.includes(suffix)) {
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.readFileRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/files/preview',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: {
                  filePath: data.filePath
                },
                WebInfo: {
                  requestId: this.readFileRequestId
                }
              }
              postMessage(message)
            } else {
              setTimeout(() => {
                axios({
                  method: 'get',
                  url: process.env.VUE_APP_BASE_API + data.filePath,
                  responseType: 'arraybuffer' // 设置响应类型为 arraybuffer
                })
                  .then((resp) => {
                    if (['.h', '.c'].includes(suffix)) {
                      const decoder = new TextDecoder('GBK')
                      const text = decoder.decode(resp.data)
                      this.codeContent = `${text}`
                    } else if (['.pdf'].includes(suffix)) {
                      this.codeContent = URL.createObjectURL(new Blob([resp.data], { type: 'application/pdf' }))
                    } else {
                      const decoder = new TextDecoder('utf-8')
                      const text = decoder.decode(resp.data)
                      this.codeContent = `${text}`
                    }
                    this.codeContentTimer = new Date().getTime()
                  })
                  .catch((err) => {
                    this.codeContent = ``
                    this.codeContentTimer = new Date().getTime()
                    this.$message.error(err)
                  })
              }, 120)
            }
          } else {
            this.codeContentTimer = new Date().getTime()
          }
        } else {
          this.codeContent = ``
          this.codeContentTimer = new Date().getTime()
        }
      }
    },
    // 寻径 从当前节点往外寻找找到顶点
    getBreadCrumbPath(node, breadcrumbPath) {
      if (node) {
        let parentNode = this.findNode(this.treeData, 'directoryId', node.parentDirectoryId, [])
        breadcrumbPath.unshift(parentNode)
        if (parentNode.parentDirectoryId !== 0) {
          this.getBreadCrumbPath(parentNode, breadcrumbPath)
        }
      }
      return breadcrumbPath
    },
    getFullPath(val) {
      if (val) {
        let node = this.findNode(this.treeData, 'directoryId', val, [])
        if (node) {
          let breadcrumbPath = [node]
          if (node?.parentDirectoryId !== 0) {
            breadcrumbPath = this.getBreadCrumbPath(node, breadcrumbPath)
          }
          return breadcrumbPath.map((item) => item.directoryName).join('/')
        } else {
          return ''
        }
      } else {
        return ''
      }
    },
    handleClose(name, index) {
      this.closePopover(true)
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.deleteDriverLibraryConfigRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/driverLibraryConfig/delete',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { configId: this.currentProjectData[name][index].configId },
          WebInfo: {
            requestId: this.deleteDriverLibraryConfigRequestId
          }
        }
        postMessage(message)
      } else {
        deleteDriverLibraryConfig({
          configId: this.currentProjectData[name][index].configId
        }).then(() => {
          this.refreshDriverLibraryConfig()
          // if (name === 'clockTemplate') {
          //   this.currentProjectData.clockTemplate.splice(index, 1)
          // } else {
          //   this.currentProjectData[name] = []
          // }
        })
      }
    },
    // 鼠标悬浮进tree
    handleMouseenter(data, show) {
      if (show) {
        this.$set(data, 'show', show)
      } else {
        if (this.popoverNode !== {} && this.popoverNode.directoryId === data.directoryId) {
          this.$set(data, 'show', true)
        } else {
          this.$set(data, 'show', false)
        }
      }
    },
    setPopoverShowTrue(data) {
      this.currentOperationData = data
      const test = JSON.parse(JSON.stringify(data))
      setTimeout(() => {
        this.$set(data, 'popoverShow', !test.popoverShow)
        if (data.popoverShow) {
          this.popoverNode = data
        } else {
          this.popoverNode = {}
        }

        this.$set(data, 'show', true)
      }, 100)
    },
    // 使节点popoverShow为false
    setPopoverShowFalse(treeData) {
      for (const item of treeData) {
        // item.popoverShow = false
        this.$set(item, 'popoverShow', false)
        this.$set(item, 'show', false)
        if (item.children) {
          this.setPopoverShowFalse(item.children)
        }
      }
    },
    // 点击popover区域以外关闭popover
    closePopover(isFlag = false) {
      var sp = document.getElementById('popoverDiv')
      if (sp) {
        if (isFlag || !sp.contains(event.target)) {
          // 这句是说如果我们点击到了id为popoverDiv以外的区域
          this.setPopoverShowFalse(this.treeData)
          this.popoverNode = {}
        }
      }
    },
    // 编辑文件、文件夹，新增文件夹
    submitForm() {
      this.$refs.formData.validate((valid) => {
        if (valid) {
          if (this.dialogType === 'edit') {
            let params = {
              directoryId: this.formData.directoryId,
              directoryName: this.formData.directoryName + this.formData.appendName
            }
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.editDirectoryNameRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/editDirectoryName',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: params,
                WebInfo: {
                  requestId: this.editDirectoryNameRequestId
                }
              }
              postMessage(message)
            } else {
              editDirectoryName(params).then((res) => {
                if (res.success) {
                  this.dialogVisible = false
                  this.currentOperationData.directoryName = params.directoryName
                  // this.handleNodeClick(this.currentData, false)
                } else {
                  this.$message.error(res.message)
                }
              })
            }
          } else {
            let params = {
              parentDirectoryId: this.formData.directoryId,
              directoryName: this.formData.directoryName
            }
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.addFolderDriverLibraryDirectoryRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/addFolder',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: params,
                WebInfo: {
                  requestId: this.addFolderDriverLibraryDirectoryRequestId
                }
              }
              postMessage(message)
            } else {
              addFolderDriverLibraryDirectory(params).then((res) => {
                this.afterAddFolderDriverLibraryDirectory(res)
              })
            }
          }
        }
      })
    },
    afterAddFolderDriverLibraryDirectory(res) {
      if (res.success) {
        this.dialogVisible = false
        let row = {
          directoryId: res.data,
          directoryName: this.formData.directoryName,
          isFile: 0,
          filePath: '',
          parentDirectoryId: this.formData.directoryId,
          children: []
        }
        this.currentOperationData.children.push(row)
        this.$nextTick(() => {
          if (row.parentDirectoryId !== 0 && !this.expandedKeys.includes(row.parentDirectoryId)) {
            this.expandedKeys.push(row.parentDirectoryId)
          }
          this.$refs.tree.setCurrentKey(row.directoryId)
          this.handleNodeClick(row, false)
        })
      } else {
        this.$message.error(res.message)
      }
    },
    // 删除文件、文件夹
    delFolderOrFile(res) {
      if (res.success) {
        this.refreshDriverLibraryConfig()
        let parentNode = this.findNode(
          this.treeData,
          'directoryId',
          this.currentOperationData.parentDirectoryId,
          []
        )
        let index = parentNode.children.findIndex(
          (item) => item.directoryId === this.currentOperationData.directoryId
        )
        parentNode.children.splice(index, 1)
        this.$refs.tree.setCurrentKey(parentNode?.directoryId)
        this.handleNodeClick(parentNode, false)
      } else {
        this.$message.error(res.message)
      }
    },
    async handleClick(name, data) {
      if (['edit', 'addChildFolder'].includes(name)) {
        this.closePopover(true)
        this.dialogType = name
        this.dialogVisible = true
        this.rules = {
          directoryName: [
            {
              required: true,
              message: '请输入' + (data.isFile ? '文件名称' : '文件夹名称'),
              trigger: ['blur', 'change']
            }
            // {
            //   validator: validateDirectoryName,
            //   trigger: ['blur', 'change'],
            //   message: (data.isFile ? '文件' : '文件夹') + '名称不符合规范'
            // }
          ]
        }
        this.dialogTitle = name === 'edit' ? '编辑文件' + (!data.isFile ? '夹' : '') : '添加文件夹'
        let directoryArr = data.directoryName.split('.')
        let appendName = ''
        let fileName = data.directoryName
        if (data.isFile) {
          appendName = directoryArr.pop()
          fileName = directoryArr.join('.')
        }
        this.formData = {
          directoryId: data.directoryId,
          directoryName: name === 'edit' ? fileName : '',
          isFile: data.isFile,
          appendName: data.isFile ? '.' + appendName : ''
        }
        this.$nextTick(() => {
          this.$refs.formData.clearValidate()
        })
      } else if (name === 'del') {
        this.$confirm(!data.isFile ? '是否确认删除整个文件夹？' : '是否确认删除文件？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.deleteDriverLibraryDirectoryRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/delete',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: { directoryId: data.directoryId },
                WebInfo: {
                  requestId: this.deleteDriverLibraryDirectoryRequestId
                }
              }
              postMessage(message)
            } else {
              deleteDriverLibraryDirectory({ directoryId: data.directoryId }).then((res) => {
                this.delFolderOrFile(res)
              })
            }
          })
          .catch(() => {})
      } else if (name === 'download') {
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          if (data.isFile) {
            this.downloadRequestId = generateUUID()
            let message = {
              RequestUrl: process.env.VUE_APP_URL + '/files/download',
              RequestMethod: 'POST',
              Headers: {
                contentType: 'application/json'
              },
              QueryParameter: {},
              RequestBody: {
                files: [
                  {
                    fileName: data.directoryName,
                    path: data.filePath
                  }
                ]
              },
              WebInfo: {
                requestId: this.downloadRequestId
              }
            }
            postMessage(message)
          } else {
            this.downloadDriverLibraryDirectoryRequestId = generateUUID()
            let message = {
              RequestUrl: process.env.VUE_APP_URL + '/driverLibraryDirectory/download',
              RequestMethod: 'POST',
              Headers: {
                contentType: 'application/json'
              },
              QueryParameter: {},
              RequestBody: { directoryId: data.directoryId },
              WebInfo: {
                requestId: this.downloadDriverLibraryDirectoryRequestId
              }
            }
            postMessage(message)
          }
          this.closePopover(true)
        } else {
          NProgress.configure({
            parent: '#myProgress'
          }).start()
          if (data.isFile) {
            downLoadFile(process.env.VUE_APP_BASE_API + data.filePath, data.directoryName)
            this.closePopover(true)
            NProgress.done()
          } else {
            downloadDriverLibraryDirectory({ directoryId: data.directoryId })
              .then((res) => {
                this.closePopover(true)
                fileDownload(res)
              })
              .finally(() => {
                NProgress.done()
              })
          }
        }
      } else if (name === 'uploadFile') {
        const input = document.getElementById('uploadFile')
        input.click()
      } else if (name === 'uploadFolder') {
        const input = document.getElementById('uploadFolder')
        input.click()
      } else if (name === 'uploadFolder1') {
        this.closePopover(true)
        this.$refs.uploadFolderDialog.is()
      } else if (['setH', 'setC', 'setTemplate', 'setDocumentation', 'setOtherDriverFile'].includes(name)) {
        this.operationType = name
        if (
          this.currentProjectData[this.driverLibraryConfig[name].key]
            .map((directory) => directory.directoryId)
            .includes(data.directoryId)
        ) {
          return
        }
        // if (data.directoryId === this.currentProjectData[this.driverLibraryConfig[name].key]?.[0]?.directoryId) {
        //   return
        // }
        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.addDriverLibraryConfigRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/driverLibraryConfig/add',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: { configType: this.driverLibraryConfig[name].configType, directoryId: data.directoryId },
            WebInfo: {
              requestId: this.addDriverLibraryConfigRequestId
            }
          }
          postMessage(message)
        } else {
          addDriverLibraryConfig({
            configType: this.driverLibraryConfig[name].configType,
            directoryId: data.directoryId
          }).then((res) => {
            if (res.success) {
              this.refreshDriverLibraryConfig()
              this.$message.success(this.driverLibraryConfig[name].desc)
              this.closePopover(true)
            } else {
              this.$message.error(res.message)
            }
          })
        }
      } else if (name === 'open') {
        if (data.directoryId === this.currentData.directoryId) return
        this.$refs.tree.setCurrentKey(data.directoryId)
        this.handleNodeClick(data, false)
      } else if (name === 'more') {
        if (!data.popoverShow) {
          await this.setPopoverShowFalse(this.treeData)
          this.setPopoverShowTrue(data)
        }
      }
    },
    refreshDriverLibraryConfig() {
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.loadDriverLibraryConfigRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/driverLibraryConfig/loadConfig',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { driverLibraryId: this.currentProjectData.driverLibraryId },
          WebInfo: {
            requestId: this.loadDriverLibraryConfigRequestId
          }
        }
        postMessage(message)
      } else {
        loadDriverLibraryConfig({ driverLibraryId: this.currentProjectData.driverLibraryId }).then((res) => {
          this.currentProjectData.cSource = res.data.cSource
          this.currentProjectData.hHeader = res.data.hHeader
          this.currentProjectData.otherDriver = res.data.otherDriver
          this.currentProjectData.driverDocumentation = res.data.driverDocumentation
          this.currentProjectData.clockTemplate = res.data.clockTemplate
        })
      }
    },
    findNode(data, prop, val, result) {
      data.forEach((item) => {
        if (item[prop] === val) {
          result.push(item)
          return false
        }
        if (item.children && item.children.length > 0) {
          this.findNode(item.children, prop, val, result)
        }
        return true
      })
      return result[0]
    },
    multipleFileUpload(files) {
      let fileList = []
      let promiseArr = []
      // console.log(files)
      for (let i = 0; i < files.length; i++) {
        // 检查文件名是否不以'~$'开头,排除临时文件
        if (!files[i].name.startsWith('~$')) {
          promiseArr.push(
            new Promise((resolve, reject) => {
              let reader = new FileReader() // new一个FileReader实例
              reader.readAsDataURL(files[i])
              reader.onload = function () {
                fileList.push({
                  // fileName: files[i].name,
                  fileName: files[i].webkitRelativePath ? files[i].webkitRelativePath : files[i].name,
                  fileContent: reader.result.split(',')[1]
                })
                resolve()
              }
            })
          )
        }
      }
      Promise.all(promiseArr).then(() => {
        this.uploadFolderRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/files/uploadFolder',
          RequestMethod: 'POST',
          Headers: {
            // contentType: 'multipart/form-data'
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { fileList },
          WebInfo: {
            requestId: this.uploadFolderRequestId
          }
        }
        postMessage(message)
      })
    },
    uploadFile() {
      const fileInput = document.getElementById('uploadFile')
      let files = fileInput.files

      if (files.length === 0) {
        this.$message.warning('不能上传空文件夹')
        return
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.currentUploadId = 'uploadFile'
        this.multipleFileUpload(files)
      } else {
        let formData = new FormData()
        for (let i = 0; i < files.length; i++) {
          formData.append('file', files[i])
        }
        uploadFolder(formData).then((res) => {
          uploadFileDriverLibraryDirectory({
            parentDirectoryId: this.currentOperationData.directoryId,
            directoryFiles: res.data.map((item) => {
              return {
                ...item,
                fileName: item.name,
                path: item.url
              }
            })
          }).then((res) => {
            fileInput.value = ''
            this.loadTreeData(res.data)
          })
        })
      }
    },
    handleUploadChange(file, fileList) {
      this.fileList = fileList
    },
    uploadFolder() {
      const fileInput = document.getElementById('uploadFolder')
      let files = fileInput.files
      if (files.length === 0) {
        this.$message.warning('不能上传空文件夹')
        return
      }
      NProgress.configure({
        parent: '#myProgress'
      }).start()
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.currentUploadId = 'uploadFolder'
        this.multipleFileUpload(files)
      } else {
        let formData = new FormData()
        for (let i = 0; i < files.length; i++) {
          // 检查文件名是否不以'~$'开头,排除临时文件
          if (!files[i].name.startsWith('~$')) {
            formData.append('file', files[i])
          }
        }
        uploadFolder(formData)
          .then((res) => {
            uploadFolderDriverLibraryDirectory({
              parentDirectoryId: this.currentOperationData.directoryId,
              directoryFiles: res.data.map((item) => {
                return {
                  ...item,
                  fileName: item.name,
                  path: item.url
                }
              })
            })
              .then((res) => {
                fileInput.value = ''
                this.loadTreeData(res.data)
              })
              .finally(() => {
                NProgress.done()
              })
          })
          .finally(() => {
            NProgress.done()
          })
      }

      // console.log(files)
      // for (let i = 0; i < files.length; i++) {
      //   this.$refs.upload.upload(files[i])
      // }
    },
    uploadFolder1(files) {
      let fileList = []
      let promiseArr = []
      for (let i = 0; i < files.length; i++) {
        promiseArr.push(
          new Promise((resolve, reject) => {
            files[i].file((file) => {
              let reader = new FileReader() // new一个FileReader实例
              reader.readAsDataURL(file)
              reader.onload = function () {
                fileList.push({
                  fileName: files[i].fullPath,
                  fileContent: reader.result.split(',')[1]
                })
                resolve()
              }
            })
          })
        )
      }
      // NProgress.configure({
      //   parent: '#myProgress'
      // }).start()
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.currentUploadId = 'uploadFolder'
        Promise.all(promiseArr).then(() => {
          this.uploadFolderRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/files/uploadFolder',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: { fileList },
            WebInfo: {
              requestId: this.uploadFolderRequestId
            }
          }
          postMessage(message)
        })
      } else {
        Promise.all(promiseArr).then(() => {
          uploadFolder({ fileList }).then((res) => {
            uploadFolderDriverLibraryDirectory({
              parentDirectoryId: this.currentOperationData.directoryId,
              directoryFiles: res.data.map((item) => {
                return {
                  ...item,
                  fileName: item.name,
                  path: item.url
                }
              })
            }).then((res) => {
              this.loadTreeData(res.data)
              this.$refs.uploadFolderDialog.handleClose()
            })
            // .finally(() => {
            //   NProgress.done()
            // })
          })
          // .finally(() => {
          //   NProgress.done()
          // })
        })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
@import '@/styles/element-variables.scss';

.driverContent {
  height: 100%;
  border-top: 1px solid #e6e6e6;
  color: #333;
  .leftContent {
    background-color: #f7faff;
    border-right: 1px solid #b9c8dc;
    padding: 20px 24px;
    display: flex;
    flex-direction: column;
    .filterInput {
      width: 100%;
      margin-bottom: 16px;
    }
    .treeContent {
      flex: 1;
      overflow-y: auto;
      .filter-tree {
        color: #333;
        background-color: #f7faff;
        &.el-tree--highlight-current /deep/ .el-tree-node.is-current > .el-tree-node__content {
          background-color: #e7edf1;
        }
        /deep/.el-tree-node__content:hover {
          background-color: #e7edf1;
        }
        /deep/.el-tree-node__expand-icon {
          color: #333;
          &.is-leaf {
            color: transparent;
          }
        }
        .treeRow {
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 100%;
          padding-right: 10px;
          .leftText {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            width: 0;
            flex: 1;
            padding-right: 5px;
          }
          .clockTemplate {
            color: $--color-primary;
          }
        }
      }
    }
  }
  .rightContent {
    display: flex;
    flex-direction: column;
    .driverSetting {
      border-bottom: 1px solid #e6e6e6;
      .templateFileContent {
        height: 24px;
        line-height: 24px;
      }
      > div {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        .myTag {
          margin-right: 8px;
          background-color: #e8ebfa;
          color: #333;
          border-radius: 14px;
        }
        > .left {
          margin-right: 50px;
        }
        .left,
        .right {
          width: 50%;
          margin-bottom: 20px;
          height: 24px;
          line-height: 24px;
          flex: 1;
        }
      }
      > div:first-of-type {
        margin-bottom: 20px;
      }
    }
    .path {
      padding-top: 20px;
      padding-bottom: 10px;
      /deep/.el-breadcrumb__item:not(:last-child) .el-breadcrumb__inner .el-link {
        color: #b9b9b9;
      }
    }
    .folderContent,
    .codeContent {
      flex: 1;
      height: 0;
    }
    .folderContent {
      .item {
        border-bottom: 1px solid #e6e6e6;
        padding: 10px 16px;
        span {
          margin-left: 10px;
        }
      }
    }
    .codeContent {
      border: 1px solid #e6e6e6;
      margin-top: 10px;
    }
  }
}
.myPopper {
  .popoverBtn {
    > div {
      padding: 5px 0;
    }
  }
}
.show-word-limit {
  /deep/.el-input__inner {
    padding-right: 45px;
  }
  /deep/.el-textarea__inner {
    margin-bottom: 40px;
  }
}
</style>
